home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / QuickTime VR / MacOS / QuickDraw™ 3D 1.0.6F4 SDK / Samples / SampleCode / START HERE - Box / Box3DSupport.c < prev    next >
Encoding:
Text File  |  1996-02-19  |  10.7 KB  |  402 lines  |  [TEXT/MPCC]

  1. // My3dSupport.c - QuickDraw 3d routines
  2. //
  3. // This file contains utility routines for QuickDraw 3d sample code.
  4. // This is a simple QuickDraw 3d application to draw a cube in the center 
  5. // of the main application window.  The routines in here handle setting up
  6. // the main display group, the view, the Macintosh 3D draw context, and the
  7. // camera and lighting. 
  8. //
  9. // This code is the basis of the introductory article in  d e v e l o p  issue 22
  10. //
  11. // Nick Thompson - January 6th 1995
  12. // 
  13. // ©1994-95 Apple computer Inc., All Rights Reserved
  14. //
  15.  
  16. #include <QuickDraw.h>
  17. #include <QDOffScreen.h>
  18.  
  19.  
  20. #include "Box3DSupport.h"
  21.  
  22.  
  23. #include "QD3DDrawContext.h"
  24. #include "QD3DRenderer.h"
  25. #include "QD3DShader.h"
  26. #include "QD3DCamera.h"
  27. #include "QD3DLight.h"
  28. #include "QD3DGeometry.h"
  29. #include "QD3DGroup.h"
  30. #include "QD3DMath.h"
  31. #include "QD3DSet.h"
  32. #include "QD3DTransform.h"
  33. #include "QD3DAcceleration.h"
  34.  
  35. static     TQ3Point3D    documentGroupCenter;
  36. static    float        documentGroupScale;
  37.  
  38.  
  39. TQ3ViewObject MyNewView(WindowPtr theWindow)
  40. {
  41.     TQ3Status                myStatus;
  42.     TQ3ViewObject            myView;
  43.     TQ3DrawContextObject        myDrawContext;
  44.     TQ3RendererObject        myRenderer;
  45.     TQ3CameraObject            myCamera;
  46.     TQ3GroupObject            myLights;
  47.     
  48.     myView = Q3View_New();
  49.     
  50.     //    Create and set draw context.
  51.     if ((myDrawContext = MyNewDrawContext(theWindow)) == nil )
  52.         goto bail;
  53.         
  54.     if ((myStatus = Q3View_SetDrawContext(myView, myDrawContext)) == kQ3Failure )
  55.         goto bail;
  56.  
  57.     Q3Object_Dispose( myDrawContext ) ;
  58.     
  59.     //    Create and set renderer.
  60.     
  61.     
  62.     
  63.     // this would use the Z-Buffer renderer
  64. #if 0
  65.  
  66.     myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeWireFrame);
  67.     if ((myStatus = Q3View_SetRenderer(myView, myRenderer)) == kQ3Failure ) {
  68.         goto bail;
  69.     }
  70.     
  71. #else
  72.  
  73.     // this would use the interactive software renderer
  74.  
  75.     if ((myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeInteractive)) != nil ) {
  76.         if ((myStatus = Q3View_SetRenderer(myView, myRenderer)) == kQ3Failure ) {
  77.             goto bail;
  78.         }
  79.         // these two lines set us up to use the best possible renderer,
  80.         // including  hardware if it is installed.
  81.         Q3InteractiveRenderer_SetDoubleBufferBypass (myRenderer, kQ3True);                        
  82.         Q3InteractiveRenderer_SetPreferences(myRenderer, kQAVendor_BestChoice, 0);
  83.  
  84.     }
  85.     else {
  86.         goto bail;
  87.     }
  88. #endif
  89.  
  90.     Q3Object_Dispose( myRenderer ) ;
  91.     
  92.     //    Create and set camera.
  93.     if ( (myCamera = MyNewCamera(theWindow)) == nil )
  94.         goto bail;
  95.         
  96.     if ((myStatus = Q3View_SetCamera(myView, myCamera)) == kQ3Failure )
  97.         goto bail;
  98.  
  99.     Q3Object_Dispose( myCamera ) ;
  100.     
  101.     //    Create and set lights.
  102.     if ((myLights = MyNewLights()) == nil )
  103.         goto bail;
  104.         
  105.     if ((myStatus = Q3View_SetLightGroup(myView, myLights)) == kQ3Failure )
  106.         goto bail;
  107.         
  108.     Q3Object_Dispose(myLights);
  109.  
  110.     //    Done!!!
  111.     return ( myView );
  112.     
  113. bail:
  114.     //    If any of the above failed, then don't return a view.
  115.     return ( nil );
  116. }
  117.  
  118. //----------------------------------------------------------------------------------
  119.  
  120. TQ3DrawContextObject MyNewDrawContext(WindowPtr theWindow)
  121. {
  122.     TQ3DrawContextData        myDrawContextData;
  123.     TQ3MacDrawContextData    myMacDrawContextData;
  124.     TQ3ColorARGB            ClearColor;
  125.     TQ3DrawContextObject    myDrawContext ;
  126.     
  127.     //    Set the background color.
  128.     ClearColor.a = 1.0;
  129.     ClearColor.r = 1.0;
  130.     ClearColor.g = 1.0;
  131.     ClearColor.b = 1.0;
  132.     
  133.     //    Fill in draw context data.
  134.     myDrawContextData.clearImageMethod = kQ3ClearMethodWithColor;
  135.     myDrawContextData.clearImageColor = ClearColor;
  136.     myDrawContextData.paneState = kQ3False;
  137.     myDrawContextData.maskState = kQ3False;
  138.     myDrawContextData.doubleBufferState = kQ3True;
  139.  
  140.     myMacDrawContextData.drawContextData = myDrawContextData;
  141.     
  142.     myMacDrawContextData.window = (CGrafPtr) theWindow;        // this is the window associated with the view
  143.     myMacDrawContextData.library = kQ3Mac2DLibraryNone;
  144.     myMacDrawContextData.viewPort = nil;
  145.     myMacDrawContextData.grafPort = nil;
  146.     
  147.     //    Create draw context and return it, if it’s nil the caller must handle
  148.     myDrawContext = Q3MacDrawContext_New(&myMacDrawContextData) ;
  149.  
  150.     return myDrawContext ;
  151. }
  152.  
  153. //----------------------------------------------------------------------------------
  154.  
  155. TQ3CameraObject MyNewCamera(WindowPtr theWindow)
  156. {
  157.     TQ3ViewAngleAspectCameraData    perspectiveData;
  158.     TQ3CameraObject                camera;
  159.     
  160.     TQ3Point3D                     from     = { 0.0, 0.0, 7.0 };
  161.     TQ3Point3D                     to         = { 0.0, 0.0, 0.0 };
  162.     TQ3Vector3D                 up         = { 0.0, 1.0, 0.0 };
  163.  
  164.     float                         fieldOfView = 1.0;
  165.     float                         hither         = 0.001;
  166.     float                         yon         = 1000;
  167.     
  168.     TQ3Status                    returnVal = kQ3Failure ;
  169.  
  170.  
  171.     perspectiveData.cameraData.placement.cameraLocation     = from;
  172.     perspectiveData.cameraData.placement.pointOfInterest     = to;
  173.     perspectiveData.cameraData.placement.upVector             = up;
  174.  
  175.     perspectiveData.cameraData.range.hither    = hither;
  176.     perspectiveData.cameraData.range.yon     = yon;
  177.  
  178.     perspectiveData.cameraData.viewPort.origin.x = -1.0;
  179.     perspectiveData.cameraData.viewPort.origin.y = 1.0;
  180.     perspectiveData.cameraData.viewPort.width = 2.0;
  181.     perspectiveData.cameraData.viewPort.height = 2.0;
  182.     
  183.     perspectiveData.fov                = fieldOfView;
  184.     perspectiveData.aspectRatioXToY    =
  185.         (float) (theWindow->portRect.right - theWindow->portRect.left) / 
  186.         (float) (theWindow->portRect.bottom - theWindow->portRect.top);
  187.         
  188.     camera = Q3ViewAngleAspectCamera_New(&perspectiveData);
  189.  
  190.     return camera ;
  191. }
  192.  
  193.  
  194. //----------------------------------------------------------------------------------
  195.  
  196. TQ3GroupObject MyNewLights()
  197. {
  198.     TQ3GroupPosition        myGroupPosition;
  199.     TQ3GroupObject            myLightList;
  200.     TQ3LightData            myLightData;
  201.     TQ3PointLightData        myPointLightData;
  202.     TQ3DirectionalLightData    myDirectionalLightData;
  203.     TQ3LightObject            myAmbientLight, myPointLight, myFillLight;
  204.     TQ3Point3D                pointLocation = { -10.0, 0.0, 10.0 };
  205.     TQ3Vector3D                fillDirection = { 10.0, 0.0, 10.0 };
  206.     TQ3ColorRGB                WhiteLight = { 1.0, 1.0, 1.0 };
  207.     
  208.     //    Set up light data for ambient light.  This light data will be used for point and fill
  209.     //    light also.
  210.  
  211.     myLightData.isOn = kQ3True;
  212.     myLightData.color = WhiteLight;
  213.     
  214.     //    Create ambient light.
  215.     myLightData.brightness = .2;
  216.     myAmbientLight = Q3AmbientLight_New(&myLightData);
  217.     if ( myAmbientLight == nil )
  218.         goto bail;
  219.     
  220.     //    Create point light.
  221.     myLightData.brightness = 1.0;
  222.     myPointLightData.lightData = myLightData;
  223.     myPointLightData.castsShadows = kQ3False;
  224.     myPointLightData.attenuation = kQ3AttenuationTypeNone;
  225.     myPointLightData.location = pointLocation;
  226.     myPointLight = Q3PointLight_New(&myPointLightData);
  227.     if ( myPointLight == nil )
  228.         goto bail;
  229.  
  230.     //    Create fill light.
  231.     myLightData.brightness = .2;
  232.     myDirectionalLightData.lightData = myLightData;
  233.     myDirectionalLightData.castsShadows = kQ3False;
  234.     myDirectionalLightData.direction = fillDirection;
  235.     myFillLight = Q3DirectionalLight_New(&myDirectionalLightData);
  236.     if ( myFillLight == nil )
  237.         goto bail;
  238.  
  239.     //    Create light group and add each of the lights into the group.
  240.     myLightList = Q3LightGroup_New();
  241.     if ( myLightList == nil )
  242.         goto bail;
  243.     myGroupPosition = Q3Group_AddObject(myLightList, myAmbientLight);
  244.     if ( myGroupPosition == 0 )
  245.         goto bail;
  246.     myGroupPosition = Q3Group_AddObject(myLightList, myPointLight);
  247.     if ( myGroupPosition == 0 )
  248.         goto bail;
  249.     myGroupPosition = Q3Group_AddObject(myLightList, myFillLight);
  250.     if ( myGroupPosition == 0 )
  251.         goto bail;
  252.  
  253.     Q3Object_Dispose( myAmbientLight ) ;
  254.     Q3Object_Dispose( myPointLight ) ;
  255.     Q3Object_Dispose( myFillLight ) ;
  256.  
  257.     //    Done!
  258.     return ( myLightList );
  259.     
  260. bail:
  261.     //    If any of the above failed, then return nothing!
  262.     return ( nil );
  263. }
  264.  
  265.  
  266.  
  267.  
  268. static void MyColorBoxFaces( TQ3BoxData *myBoxData )
  269. {
  270.     TQ3ColorRGB                faceColor ;
  271.     short                     face ;
  272.     
  273.     // sanity check - you need to have set up 
  274.     // the face attribute set for the box data 
  275.     // before calling this.
  276.     
  277.     if( myBoxData->faceAttributeSet == NULL )
  278.         return ;
  279.         
  280.     // make each face of a box a different color
  281.     
  282.     for( face = 0; face < 6; face++) {
  283.         
  284.         myBoxData->faceAttributeSet[face] = Q3AttributeSet_New();
  285.         switch( face ) {
  286.             case 0:
  287.                 faceColor.r = 1.0;
  288.                 faceColor.g = 0.0;
  289.                 faceColor.b = 0.0;
  290.                 break;
  291.             
  292.             case 1:
  293.                 faceColor.r = 0.0;
  294.                 faceColor.g = 1.0;
  295.                 faceColor.b = 0.0;
  296.                 break;
  297.             
  298.             case 2:
  299.                 faceColor.r = 0.0;
  300.                 faceColor.g = 0.0;
  301.                 faceColor.b = 1.0;
  302.                 break;
  303.             
  304.             case 3:
  305.                 faceColor.r = 1.0;
  306.                 faceColor.g = 1.0;
  307.                 faceColor.b = 0.0;
  308.                 break;
  309.             
  310.             case 4:
  311.                 faceColor.r = 1.0;
  312.                 faceColor.g = 0.0;
  313.                 faceColor.b = 1.0;
  314.                 break;
  315.             
  316.             case 5:
  317.                 faceColor.r = 0.0;
  318.                 faceColor.g = 1.0;
  319.                 faceColor.b = 1.0;
  320.                 break;
  321.         }
  322.         Q3AttributeSet_Add(myBoxData->faceAttributeSet[face], kQ3AttributeTypeDiffuseColor, &faceColor);
  323.     }
  324. }
  325.  
  326. static TQ3GroupPosition MyAddTransformedObjectToGroup( TQ3GroupObject theGroup, TQ3Object theObject, TQ3Vector3D *translation )
  327. {
  328.     TQ3TransformObject    transform;
  329.  
  330.     transform = Q3TranslateTransform_New(translation);
  331.     Q3Group_AddObject(theGroup, transform);    
  332.     Q3Object_Dispose(transform);
  333.     return Q3Group_AddObject(theGroup, theObject);    
  334. }
  335.  
  336.  
  337. TQ3GroupObject MyNewModel()
  338. {
  339.     TQ3GroupObject            myGroup = NULL;
  340.     TQ3GeometryObject        myBox;
  341.     TQ3BoxData                myBoxData;
  342.     TQ3ShaderObject            myIlluminationShader ;
  343.     TQ3Vector3D                translation;
  344.     
  345.     TQ3SetObject                faces[6] ;
  346.     short                    face ;
  347.             
  348.     // Create a group for the complete model.
  349.     // do not use Q3OrderedDisplayGroup_New since in this
  350.     // type of group all of the translations are applied before
  351.     // the objects in the group are drawn, in this instance we 
  352.     // dont want this.
  353.     if ((myGroup = Q3DisplayGroup_New()) != NULL ) {
  354.             
  355.         // Define a shading type for the group
  356.         // and add the shader to the group
  357.         myIlluminationShader = Q3PhongIllumination_New();
  358.         Q3Group_AddObject(myGroup, myIlluminationShader);
  359.  
  360.         // set up the colored faces for the box data
  361.         myBoxData.faceAttributeSet = faces;
  362.         myBoxData.boxAttributeSet = nil;
  363.         MyColorBoxFaces( &myBoxData ) ;
  364.         
  365.         // create the box itself
  366.         Q3Point3D_Set(&myBoxData.origin, 0, 0, 0);
  367.         Q3Vector3D_Set(&myBoxData.orientation, 0, 1, 0);
  368.         Q3Vector3D_Set(&myBoxData.majorAxis, 0, 0, 1);    
  369.         Q3Vector3D_Set(&myBoxData.minorAxis, 1, 0, 0);    
  370.         myBox = Q3Box_New(&myBoxData);
  371.         
  372.         // put four copies of the box into the group, each one with its own translation
  373.         translation.x = 0;translation.y = 0;translation.z = 0;
  374.         MyAddTransformedObjectToGroup( myGroup, myBox, &translation ) ;
  375.         
  376.         translation.x = 2;translation.y = 0;translation.z = 0;
  377.         MyAddTransformedObjectToGroup( myGroup, myBox, &translation ) ;
  378.         
  379.         translation.x = 0;translation.y = 0;translation.z = -2;
  380.         MyAddTransformedObjectToGroup( myGroup, myBox, &translation ) ;
  381.         
  382.         translation.x = -2;translation.y = 0;translation.z = 0;
  383.         MyAddTransformedObjectToGroup( myGroup, myBox, &translation ) ;
  384.     }
  385.     
  386.     // dispose of the objects we created here
  387.     if( myIlluminationShader ) 
  388.         Q3Object_Dispose(myIlluminationShader);    
  389.             
  390.     for( face = 0; face < 6; face++) {
  391.         if( myBoxData.faceAttributeSet[face] != NULL )
  392.             Q3Object_Dispose(myBoxData.faceAttributeSet[face]);
  393.     }
  394.     
  395.     if( myBox ) 
  396.         Q3Object_Dispose( myBox );
  397.     
  398.     //    Done!
  399.     return ( myGroup );
  400. }
  401.  
  402.